﻿using System;

namespace SharpShare.Afp.Protocol.Handlers {
    internal class AfpMapIDRequestHandler : IAfpRequestHandler {
        public byte CommandCode {
            get { return 21; }
        }

        public AfpResultCode Process(IAfpSession session, DsiHeader dsiHeader, AfpStream requestStream, AfpStream responseStream) {
            AfpMapIdSubfunction subfunction = requestStream.ReadEnum<AfpMapIdSubfunction>();

            string user = null;
            string group = null;
            Guid groupGuid = Guid.Empty;

            IShareService server = (IShareService)session.Server;

            switch (subfunction) {
                case AfpMapIdSubfunction.kGroupIDToName:
                case AfpMapIdSubfunction.kGroupIDToUTF8Name: {
                        int groupId = requestStream.ReadInt32();
                        Guid realGroupId;
                        if (!session.UserGroupAssigner.TryGet(groupId, out realGroupId)) {
                            return AfpResultCode.FPItemNotFound;
                        }

                        group = session.Server.UserManager.GetGroup(realGroupId);
                        groupGuid = realGroupId;

                        break;
                    }
                case AfpMapIdSubfunction.kGroupUUIDToUTF8Name: {
                        Guid groupId = new Guid(requestStream.ReadBytes(16));
                        group = session.Server.UserManager.GetGroup(groupId);
                        groupGuid = groupId;
                        break;
                    }
                case AfpMapIdSubfunction.kUserIDToName:
                case AfpMapIdSubfunction.kUserIDToUTF8Name: {
                        int userId = requestStream.ReadInt32();
                        Guid realUserId;
                        if (!session.UserGroupAssigner.TryGet(userId, out realUserId)) {
                            return AfpResultCode.FPItemNotFound;
                        }

                        user = session.Server.UserManager.GetUser(realUserId).Name;

                        break;
                    }
                case AfpMapIdSubfunction.kUserUUIDToUTF8Name: {
                        Guid userId = new Guid(requestStream.ReadBytes(16));
                        user = session.Server.UserManager.GetUser(userId).Name;
                        break;
                    }
                default:
                    return AfpResultCode.FPParamErr;
            }

            if (user == null && group == null) {
                return AfpResultCode.FPItemNotFound;
            }

            if (subfunction == AfpMapIdSubfunction.kGroupUUIDToUTF8Name || subfunction == AfpMapIdSubfunction.kUserUUIDToUTF8Name) {
                string name;
                Guid guid;

                if (user != null) {
                    responseStream.WriteUInt32(1); // User

                    guid = session.Server.UserManager.GetUser(user).Id;
                    name = user;
                } else {
                    responseStream.WriteUInt32(2); // Group 

                    guid = groupGuid;
                    name = group;
                }

                responseStream.WriteInt32(session.UserGroupAssigner.Get(guid));
                responseStream.WriteBytes(System.Text.Encoding.UTF8.GetBytes(name));
            } else {
                string name = (user ?? group);

                bool utf = (subfunction == AfpMapIdSubfunction.kGroupIDToUTF8Name || subfunction == AfpMapIdSubfunction.kUserIDToUTF8Name);

                if (utf) {
                    responseStream.WriteUTF8String(name);
                } else {
                    responseStream.WritePascalString(name);
                }
            }

            return AfpResultCode.FPNoErr;
        }
    }
}
